home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / mus / play / tracker_4_31.lzh / tracker / Arch / Hpux / 3_audio.c next >
C/C++ Source or Header  |  1995-05-15  |  10KB  |  434 lines

  1. /* -*-C-*-
  2.     vi:ts=3 sw=3:
  3. *******************************************************************************
  4. *
  5. * File:        hpux_audio.c
  6. * RCS:        $Header: /users/algo/espie/projects/tracker/Arch/Hpux/RCS/3_audio.c,v 1.5 1995/05/15 12:19:05 espie Exp espie $
  7. * Description:    HP-UX audio hardware interface for tracker
  8. * Author:    Darryl Okahata (darrylo@sr.hp.com)
  9. * Created:    Thu Dec 16 12:09:53 1993
  10. * Modified:     Mon Dec 20 12:17:02 1993 (Darryl Okahata) darrylo@mina
  11. * Language:    C
  12. * Package:    N/A
  13. * Status:    Experimental
  14. *
  15. * (C) Copyright 1993, Hewlett-Packard, all rights reserved.
  16. *
  17. *******************************************************************************
  18.  
  19.  */
  20.  
  21. #include "defs.h"
  22. #include <errno.h>
  23. #include <sys/socket.h>
  24.  
  25. #include <audio/Alib.h>
  26.  
  27. #include "extern.h"
  28.  
  29.  
  30. #define DEFAULT_SET_MIX
  31. #define DEFAULT_BUFFERS
  32. #define NEW_OUTPUT_SAMPLES_AWARE
  33. #include "Arch/common.c"
  34.  
  35.  
  36. #define STEREO_CHANNELS        (ALeftOutputChMask | ARightOutputChMask)
  37.  
  38. extern AGainDB        volume;        /* volume in dB -- in main.c */
  39. extern char        use_speaker;    /* in main.c */
  40.  
  41. LOCAL Audio        *audio;
  42. LOCAL ADataFormat    *available_formats;
  43. LOCAL long        available_formats_len;
  44. LOCAL AOutputChMask    available_channels;
  45. LOCAL AByteOrder    byte_order;
  46. LOCAL AudioAttributes    audio_attributes;
  47. LOCAL AGainEntry    gain_entry[4];
  48. LOCAL SSPlayParams    stream_parameters;
  49. LOCAL ATransID        xid;
  50. LOCAL SStream        audio_stream;
  51. LOCAL int        stream_socket;
  52.  
  53.  
  54. LOCAL ADataFormat    audio_format;
  55. LOCAL int        max_index;
  56. LOCAL long        buffer_size;
  57.  
  58.  
  59. LOCAL int round_sampling_rate(audio, f)
  60. Audio    *audio;
  61. int    f;
  62. {
  63.     int best = 0;
  64.     int i;
  65.  
  66.     for (i = 0; i < audio->n_sampling_rate; i++) {
  67.     if (abs(audio->sampling_rate_list[i] - f) < abs(best - f)) {
  68.         best = audio->sampling_rate_list[i];
  69.     }
  70.     }
  71.     return best;
  72. }
  73.  
  74.  
  75. LOCAL format_available(fmt)
  76. ADataFormat    fmt;
  77. {
  78.     int        i;
  79.  
  80.     for (i = 0; i < available_formats_len; ++i) {
  81.     if (available_formats[i] == fmt) {
  82.         break;
  83.     }
  84.     }
  85.     if (i >= available_formats_len) {
  86.     return (0);
  87.     }
  88.     return (1);
  89. }
  90.  
  91.  
  92. /*
  93.  * It would be nice if we could use AGetErrorText(), but this requires that
  94.  * an audio pointer be passed to it, and this pointer could be NULL.
  95.  */
  96. LOCAL void die(msg, error)
  97. char        *msg;
  98. AError        error;
  99. {
  100.     char    *errbuf, buf[1000];    /* memory is cheap, life is short */
  101.  
  102.     if (msg == NULL) {
  103.     msg = "";
  104.     }
  105.     switch (error) {
  106.     case AENoError:
  107.     errbuf = "(No audio error -- huh?  This should never happen!)";
  108.     break;
  109.     case AESystemCall:
  110.     errbuf = "System call error";
  111.     break;
  112.     case AEBadAudio:
  113.     errbuf = "Bad audio";
  114.     break;
  115.     case AEBadValue:
  116.     errbuf = "Bad audio value";
  117.     break;
  118.     case AEHostNotFound:
  119.     errbuf = "Audio host not found";
  120.     break;
  121.     case AENoSuchAudioNumber:
  122.     errbuf = "No such audio number";
  123.     break;
  124.     case AEBadFileFormat:
  125.     errbuf = "Bad audio file format";
  126.     break;
  127.     case AEBadDataFormat:
  128.     errbuf = "Bad audio data format";
  129.     break;
  130.     case AEFileNotFound:
  131.     errbuf = "Audio file not found";
  132.     break;
  133.     case AEBadLinkID:
  134.     errbuf = "Audio bad link ID";
  135.     break;
  136.     case AEBadGainMatrix:
  137.     errbuf = "Bad audio gain matrix";
  138.     break;
  139.     case AEBadFileHdr:
  140.     errbuf = "Bad audio file header";
  141.     break;
  142.     case AEUnrecognizableFormat:
  143.     errbuf = "Unrecognizable audio format";
  144.     break;
  145.     case AEBadAttribute:
  146.     errbuf = "Bad audio attribute";
  147.     break;
  148.     case AEBadOffset:
  149.     errbuf = "Audio bad offset";
  150.     break;
  151.     case AEBadTransactionID:
  152.     errbuf = "Bad audio transaction ID";
  153.     break;
  154.     case AECantDetermineFormat:
  155.     errbuf = "Audio can't determine format";
  156.     break;
  157.     case AEOutOfMemory:
  158.     errbuf = "out of memory (audio)";
  159.     break;
  160.     case AEOpenFailed:
  161.     errbuf = "Audio open failed";
  162.     break;
  163.     case AEBadSamplingRate:
  164.     errbuf = "Bad audio sampling rate";
  165.     break;
  166.     case AEBadSoundBucket:
  167.     errbuf = "Audio bad sound bucket";
  168.     break;
  169.     case AEBadSoundStream:
  170.     errbuf = "Audio bad sound stream";
  171.     break;
  172.     case AETransactionBusy:
  173.     errbuf = "Audio transaction busy";
  174.     break;
  175.     case AEllbdNotStarted:
  176.     errbuf = "llbd daemon not running";
  177.     break;
  178.     case AERPCFailed:
  179.     errbuf = "Audio RPC failed";
  180.     break;
  181.     case AELibraryMismatch:
  182.     errbuf = "Audio library mismatch";
  183.     break;
  184.     default:
  185.     sprintf(buf, "(unknown audio error %d)", (int) error);
  186.     errbuf = buf;
  187.     break;
  188.     }
  189.      notice(msg);
  190.      end_all(errbuf);
  191. }
  192.  
  193.  
  194. int open_audio(freq, stereo_flag)
  195. int freq;
  196. int stereo_flag;
  197. {
  198.     long        status_return;
  199.     AudioAttrMask    valid_attributes;
  200.     char        *speaker;
  201.     int        i;
  202.  
  203.     stereo = stereo_flag;
  204.  
  205.     if ((audio = AOpenAudio(NULL, &status_return)) == NULL) {
  206.     die("could not open audio: ", status_return);
  207.     }
  208.  
  209.     available_formats = ADataFormats(audio);
  210.     available_formats_len = ANumDataFormats(audio);
  211.     if (format_available(ADFLin16)) {
  212.     audio_format = ADFLin16;
  213.     dsize = 2;        /* for ADFLin16 */
  214.     } else if (format_available(ADFLin8)) {
  215.     audio_format = ADFLin8;
  216.     dsize = 1;        /* for ADFLin8 */
  217.     } else {
  218.      end_all("Neither ADFLin16/ADFLin8 supported by the audio device");
  219.     }
  220.  
  221.     available_channels = AOutputChannels(audio);
  222.  
  223.     valid_attributes = ASDataFormatMask | ASBitsPerSampleMask |
  224.     ASSamplingRateMask | ASChannelsMask;
  225.     audio_attributes = *ABestAudioAttributes(audio);
  226.     audio_attributes.type = ATSampled;
  227.     audio_attributes.attr.sampled_attr.data_format = ADFLin16;
  228.     audio_attributes.attr.sampled_attr.bits_per_sample = 16;
  229.  
  230.     if (freq <= 0) {
  231.     /*
  232.      * Use value closest to CD-quality audio
  233.      */
  234.     freq = 44100;
  235.     }
  236.     freq = round_sampling_rate(audio, freq);
  237.     audio_attributes.attr.sampled_attr.sampling_rate = freq;
  238.  
  239.     audio_attributes.attr.sampled_attr.duration.type = ATTFullLength;
  240.     valid_attributes |= ASDurationMask;
  241.  
  242.     if (stereo &&
  243.     ((available_channels & (STEREO_CHANNELS)) == STEREO_CHANNELS)) {
  244.     audio_attributes.attr.sampled_attr.channels = 2;
  245.     audio_attributes.attr.sampled_attr.interleave = 1;
  246.     valid_attributes |= ASInterleaveMask;
  247.     } else {
  248.     audio_attributes.attr.sampled_attr.channels = 1;
  249.     }
  250.  
  251.     /*
  252.      * Select attributes for playback
  253.      */
  254.     AChoosePlayAttributes(audio, ABestAudioAttributes(audio),
  255.               valid_attributes, &audio_attributes,
  256.               &byte_order, &status_return);
  257.     if (byte_order != AMSBFirst) {
  258.      end_all("Little endian byte ordering not supported");
  259.     }
  260.  
  261.     /*
  262.      * Use the external jack, unless the user overrides this on the
  263.      * command-line, or SPEAKER is set.     (The command line stuff is done in
  264.      * main.c.)
  265.      */
  266.     if ((speaker = getenv( "SPEAKER" )) != NULL) {
  267.     if ((*speaker == 'i') || (*speaker == 'I')) {
  268.         use_speaker = 1;
  269.     }
  270.     }
  271.  
  272.     stream_parameters.priority = APriorityNormal;
  273.  
  274.     switch(audio_attributes.attr.sampled_attr.channels) {
  275.     case 1:
  276.     gain_entry[0].u.o.out_ch = AOCTMono;
  277.     gain_entry[0].gain = volume;
  278.     gain_entry[0].u.o.out_dst =
  279.         (use_speaker) ? AODTMonoIntSpeaker : AODTMonoJack;
  280.     break;
  281.     case 2:
  282.     default:    /* assume no more than 2 channels */
  283.     gain_entry[0].u.o.out_ch = AOCTLeft;
  284.     gain_entry[0].gain = volume;
  285.     gain_entry[0].u.o.out_dst =
  286.         (use_speaker) ? AODTLeftIntSpeaker : AODTLeftJack;
  287.     gain_entry[1].u.o.out_ch = AOCTRight;
  288.     gain_entry[1].gain = volume;
  289.     gain_entry[1].u.o.out_dst =
  290.         (use_speaker) ? AODTRightIntSpeaker : AODTRightJack;
  291.     break;
  292.     }
  293.  
  294.     stream_parameters.gain_matrix.type = AGMTOutput;       /* gain matrix */
  295.     stream_parameters.gain_matrix.num_entries =
  296.     audio_attributes.attr.sampled_attr.channels;
  297.     stream_parameters.gain_matrix.gain_entries = gain_entry;
  298.     stream_parameters.play_volume = AUnityGain;           /* play volume */
  299.     stream_parameters.event_mask = 0;               /* don't solicit any
  300.                                   events */
  301.  
  302.     /*
  303.      * create an audio stream
  304.      */
  305.     xid = APlaySStream(audio, valid_attributes, &audio_attributes,
  306.                &stream_parameters, &audio_stream, NULL);
  307.  
  308.     /*
  309.      * create a stream socket
  310.      */
  311.     stream_socket = socket(AF_INET, SOCK_STREAM, 0);
  312.     if(stream_socket < 0) {
  313.      end_all("Socket creation failed");
  314.     }
  315.  
  316.     /*
  317.      * connect the stream socket to the audio stream port
  318.      */
  319.     status_return = connect(stream_socket,
  320.                 (struct sockaddr *)&audio_stream.tcp_sockaddr,
  321.                 sizeof(struct sockaddr_in));
  322.     if (status_return < 0) {
  323.      end_all("Connect failed");
  324.     }
  325.  
  326.     buffer_size = dsize * audio_attributes.attr.sampled_attr.channels
  327.     * audio_attributes.attr.sampled_attr.sampling_rate;
  328.     buffer = (char *) malloc(buffer_size);
  329.     buffer16 = (short *) buffer;
  330.     if (!buffer) {
  331.      end_all("Unable to allocate memory for buffer");
  332.     }
  333.     switch (audio_format) {
  334.     case ADFLin16:
  335.     samples_max = buffer_size / 2 - 1;
  336.     break;
  337.     case ADFLin8:
  338.     samples_max = buffer_size - 1;
  339.     break;
  340.     default:
  341.         end_all("Bad");
  342.     break;
  343.     }
  344.  
  345.     return (audio_attributes.attr.sampled_attr.sampling_rate);
  346. }
  347.  
  348.  
  349. void set_synchro(s)
  350. int s;
  351. {
  352.     /* not implemented */
  353. }
  354.  
  355.  
  356. int update_frequency()
  357. {
  358.     /* not implemented */
  359.     return 0;
  360. }
  361.  
  362.  
  363. void flush_buffer()
  364. {
  365.     int        len_written, len_left;
  366.     char    *buf;
  367.  
  368.     len_left = idx * 2;
  369.     buf = buffer;
  370.     while (len_left > 0) {
  371.     if((len_written = write(stream_socket, buf, len_left)) < 0) {
  372.         end_all("Write failed");
  373.     }
  374.     len_left -= len_written;
  375.     buf += len_written;
  376.     }
  377.     idx = 0;
  378. }
  379.  
  380.  
  381. void output_samples(left, right, n)
  382. int left, right, n;
  383.     {
  384.    if (idx >= max_index) 
  385.         flush_buffer();
  386.     switch(audio_format)
  387.         {
  388.     case ADFLin16:
  389.         add_samples16(left, right, n);
  390.         break;
  391.     case ADFLin8:
  392.         add_samples8(left, right, n);
  393.         break;
  394.     default:
  395.         end_all("tracker/hp3: Unkown audio format");
  396.         break;
  397.         }
  398.    }
  399.  
  400.  
  401. void discard_buffer()
  402. {
  403.     /* not implemented -- is this needed??? */
  404. }
  405.  
  406.  
  407. void close_audio()
  408. {
  409.     close(stream_socket);
  410.  
  411.     /*
  412.      * set close mode to prevent playback from stopping
  413.      *    when we close audio connection
  414.      */
  415.     ASetCloseDownMode(audio, AKeepTransactions, NULL);
  416.  
  417.     /*
  418.      *    That's all, folks!
  419.      */
  420.     ACloseAudio(audio, NULL);
  421.     audio = NULL;
  422. }
  423.  
  424.  
  425. /*
  426.  * Local Variables:
  427.  * c-indent-level: 4
  428.  * c-continued-statement-offset: 4
  429.  * c-brace-offset: -4
  430.  * c-argdecl-indent: 0
  431.  * c-label-offset: -4
  432.  * End:
  433.  */
  434.